const svgCaptcha = require('svg-captcha');
const crypto = require('crypto');
const config = require('../../config');
const { getLogger } = require('../logger');
const { getRedisClient, isRedisEnabled } = require('../infra/redisClient');
const logger = getLogger('services.captchaService');

// 验证码存储（内存）
const captchaStore = new Map();
const cleanupInterval = config?.captcha?.cleanupInterval || 30000;

// 定时清理过期验证码
setInterval(() => {
    if (type === 'redis') {
        return;
    }
    const now = Date.now();
    let cleaned = 0;
    for (const [id, data] of captchaStore.entries()) {
        if (now > data.expiresAt) {
            captchaStore.delete(id);
            cleaned++;
        }
    }
    if (cleaned > 0) {
        logger.info('验证码内存清理', { cleaned, remain: captchaStore.size });
    }
}, cleanupInterval);

const type = String(config?.captcha?.type || 'memory').toLowerCase();
const prefix = String(config?.captcha?.cachePrefix || 'captcha_');

// 创建验证码
const createCaptcha = async () => {
    const options = config.captcha;
    const captcha = svgCaptcha.create(options);
    
    const id = crypto.randomUUID();
    const code = String(captcha.text || '').toLowerCase();
    const expireSeconds = Number(config?.captcha?.expireTime || 180);
    const expiresAt = Date.now() + expireSeconds * 1000;

    if (type === 'redis' && isRedisEnabled() && getRedisClient()) {
        const key = `${prefix}${id}`;
        const client = getRedisClient();
        await client.set(key, JSON.stringify({ code, createdAt: Date.now() }), 'EX', expireSeconds);
        logger.info('验证码创建成功', { id, store: 'redis', key, ttl: expireSeconds });
    } else {
        captchaStore.set(id, { code, expiresAt, createdAt: Date.now() });
        logger.info('验证码创建成功', { id, store: 'memory', expiresIn: expireSeconds });
    }

    return { id, svg: captcha.data, expiresAt, expiresInSeconds: expireSeconds };
};

// 验证验证码
const verifyCaptcha = async (captchaId, inputCode) => {
    if (!captchaId || !inputCode) return { ok: false, reason: 'missing_params' };
    const input = String(inputCode).toLowerCase();

    if (type === 'redis' && isRedisEnabled() && getRedisClient()) {
        const client = getRedisClient();
        const key = `${prefix}${captchaId}`;
        const val = await client.get(key);
        if (!val) {
            logger.warn('验证码验证失败', { id: captchaId, store: 'redis', reason: 'expired' });
            return { ok: false, reason: 'expired' };
        }
        const data = JSON.parse(val);
        const ok = input === data.code;
        if (ok) await client.del(key);
        logger.info('验证码验证成功', { id: captchaId, store: 'redis', ok });
        return { ok, reason: ok ? null : 'mismatch' };
    } else {
        const data = captchaStore.get(captchaId);
        if (!data) {
            logger.warn('验证码验证失败', { id: captchaId, store: 'memory', reason: 'not_found' });
            return { ok: false, reason: 'not_found' };
        }
        if (Date.now() > data.expiresAt) {
            captchaStore.delete(captchaId);
            logger.warn('验证码验证失败', { id: captchaId, store: 'memory', reason: 'expired' });
            return { ok: false, reason: 'expired' };
        }
        const ok = input === data.code;
        if (ok) captchaStore.delete(captchaId);
        logger.info('验证码验证成功', { id: captchaId, store: 'memory', ok });
        return { ok, reason: ok ? null : 'mismatch' };
    }
};

// 获取验证码数量
const getCaptchaCount = async () => {
    if (type === 'redis' && isRedisEnabled() && getRedisClient()) {
        const client = getRedisClient();
        let cursor = '0';
        let count = 0;
        do {
            const res = await client.scan(cursor, 'MATCH', `${prefix}*`, 'COUNT', 100);
            cursor = res[0];
            count += res[1].length;
        } while (cursor !== '0');
        logger.debug('验证码数量', { store: 'redis', total: count });
        return count;
    }
    logger.debug('验证码数量', { store: 'memory', total: captchaStore.size });
    return captchaStore.size;
};

// 获取验证码状态
const getCaptchaStatus = async () => {
    if (type === 'redis' && isRedisEnabled() && getRedisClient()) {
        const total = await getCaptchaCount();
        logger.debug('验证码状态', { store: 'redis', total });
        return { total, valid: null, expired: null, store: [] };
    }
    const now = Date.now();
    const validCount = Array.from(captchaStore.values()).filter(d => now < d.expiresAt).length;
    const expiredCount = captchaStore.size - validCount;
    logger.debug('验证码状态', { store: 'memory', total: captchaStore.size, valid: validCount, expired: expiredCount });
    return {
        total: captchaStore.size,
        valid: validCount,
        expired: expiredCount,
        store: Array.from(captchaStore.entries()).map(([id, data]) => ({
            id,
            code: data.code,
            createdAt: new Date(data.createdAt).toLocaleString(),
            expiresAt: new Date(data.expiresAt).toLocaleString(),
            isExpired: now > data.expiresAt
        }))
    };
};

// 清理所有验证码
const clearAllCaptcha = async () => {
    if (type === 'redis' && isRedisEnabled() && getRedisClient()) {
        const client = getRedisClient();
        let cursor = '0';
        let keys = [];
        do {
            const res = await client.scan(cursor, 'MATCH', `${prefix}*`, 'COUNT', 100);
            cursor = res[0];
            keys = keys.concat(res[1]);
        } while (cursor !== '0');
        if (keys.length > 0) await client.del(keys);
        logger.info('验证码清理', { store: 'redis', cleared: keys.length });
        return keys.length;
    }
    const count = captchaStore.size;
    captchaStore.clear();
    logger.info('验证码清理', { store: 'memory', cleared: count });
    return count;
};

module.exports = { createCaptcha, verifyCaptcha, getCaptchaCount, getCaptchaStatus, clearAllCaptcha };